package encore.portal.portlet.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.EventPortlet;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.Portlet;
import javax.portlet.PortletContext;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import javax.portlet.ResourceServingPortlet;
import javax.portlet.filter.ActionFilter;
import javax.portlet.filter.EventFilter;
import javax.portlet.filter.FilterChain;
import javax.portlet.filter.RenderFilter;
import javax.portlet.filter.ResourceFilter;

import encore.portal.portlet.models.Filter;

public class FilterChainImpl implements FilterChain {

	private List<Filter> filterList=new ArrayList<Filter>();
	
	private String lifeCycle;
	
	private Portlet portlet;
	
	private EventPortlet eventPortlet;
	
	private ResourceServingPortlet resourceServingPortlet;
	
	private ClassLoader loader;
	
	private PortletContext portletContext;
	private int filterListIndex=0;
	
	public FilterChainImpl(String lifeCycle)
	{
		this.lifeCycle=lifeCycle;
	}
	
	
	public void processFilter(EventRequest request,EventResponse response,EventPortlet eventPortlet,PortletContext portletContext)throws IOException,PortletException{
		this.eventPortlet=eventPortlet;
		this.loader=Thread.currentThread().getContextClassLoader();
		this.portletContext=portletContext;
		doFilter(request, response);
	}
	
	public void processFilter(ResourceRequest request,ResourceResponse response,ResourceServingPortlet resourceServingPortlet,PortletContext portletContext)throws IOException,PortletException{
		this.resourceServingPortlet=resourceServingPortlet;
		this.loader=Thread.currentThread().getContextClassLoader();
		this.portletContext=portletContext;
		doFilter(request, response);
	}
	
	public void processFilter(ActionRequest request,ActionResponse response,Portlet portlet,PortletContext portletContext)throws IOException,PortletException{
		this.portlet=portlet;
		this.loader=Thread.currentThread().getContextClassLoader();
		this.portletContext=portletContext;
		doFilter(request, response);
	}
	
	public void processFilter(RenderRequest request,RenderResponse response,Portlet portlet,PortletContext portletContext)throws IOException,PortletException{
		this.portlet=portlet;
		this.loader=Thread.currentThread().getContextClassLoader();
		this.portletContext=portletContext;
		doFilter(request, response);
	}
	
	public void addFilter(Filter filter)
	{
		filterList.add(filter);
	}
	
	@Override
	public void doFilter(ActionRequest request, ActionResponse response)
			throws IOException, PortletException {
		if(filterListIndex<filterList.size())
		{
			Filter filter=filterList.get(filterListIndex);
			filterListIndex++;
			try{
				ActionFilter actionFilter=(ActionFilter)loader.loadClass(filter.getFilterClass()).newInstance();
			    FilterConfigImpl filterConfig=new FilterConfigImpl(filter.getFilterName(), filter.getInitParams(), portletContext);
			    actionFilter.init(filterConfig);
			    actionFilter.doFilter(request, response, this);
			    actionFilter.destroy();
			}catch(InstantiationException e)
			{
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}
			
		}else
		{
			portlet.processAction(request, response);
		}
	}

	@Override
	public void doFilter(EventRequest request, EventResponse response)
			throws IOException, PortletException {
		if (filterListIndex <filterList.size()){
            Filter filter = filterList.get(filterListIndex);
            filterListIndex++;
            try {
                EventFilter eventFilter = (EventFilter) loader.loadClass(filter.getFilterClass()).newInstance();
                FilterConfigImpl filterConfig = new FilterConfigImpl(filter.getFilterName(),filter.getInitParams(),portletContext);
                eventFilter.init(filterConfig);
                eventFilter.doFilter(request, response, this);
                eventFilter.destroy();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        else{
            eventPortlet.processEvent(request, response);
        }
	}

	@Override
	public void doFilter(RenderRequest request, RenderResponse response)
			throws IOException, PortletException {
		if (filterListIndex <filterList.size()){
            Filter filter = filterList.get(filterListIndex);
            filterListIndex++;
            try {
                RenderFilter renderFilter = (RenderFilter) loader.loadClass(filter.getFilterClass()).newInstance();
                FilterConfigImpl filterConfig = new FilterConfigImpl(filter.getFilterName(),filter.getInitParams(),portletContext);
                renderFilter.init(filterConfig);
                renderFilter.doFilter(request, response, this);
                renderFilter.destroy();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        else{
            portlet.render(request, response);
        }
	}

	@Override
	public void doFilter(ResourceRequest request, ResourceResponse response)
			throws IOException, PortletException {
		  if (filterListIndex <filterList.size()){
	            Filter filter = filterList.get(filterListIndex);
	            filterListIndex++;
	            try {
	                ResourceFilter resourceFilter = (ResourceFilter) loader.loadClass(filter.getFilterClass()).newInstance();
	                FilterConfigImpl filterConfig = new FilterConfigImpl(filter.getFilterName(),filter.getInitParams(),portletContext);
	                resourceFilter.init(filterConfig);
	                resourceFilter.doFilter(request, response, this);
	                resourceFilter.destroy();
	            } catch (InstantiationException e) {
	                e.printStackTrace();
	            } catch (IllegalAccessException e) {
	                e.printStackTrace();
	            } catch (ClassNotFoundException e) {
	                e.printStackTrace();
	            }
	        }
	        else{
	            resourceServingPortlet.serveResource(request, response);
	        }
	}

}
